package com.mathdroid.gui.main.character;

import java.awt.Component;
import java.awt.Container;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.LinkedList;

import javax.swing.SwingUtilities;

/**
 * This FocusListener adds itself to every component of an ItemSlotPopup.
 * If no component has user focus, the PopUp will be disposed.
 */
public final class PopupFocusListener implements FocusListener {

	/**
	 * The parent PopUp.
	 */
	private ItemSlotPopup parent = null;
	
	/**
	 * The components of the parent component.
	 */
	private LinkedList<Component> components = new LinkedList<Component>();
	
	/**
	 * Create a new focus listener.
	 * @param p Parent component.
	 */
	public PopupFocusListener(final ItemSlotPopup p) {
		super();
		this.parent = p;
		
		this.addListenerToComponentChildren(this.parent);
	}
	
	/**
	 * Add this listener to every child of the component.
	 * @param d Component.
	 */
	private void addListenerToComponentChildren(final Component d) {
		
		if (d instanceof Container) {
			for (Component c : ((Container) d).getComponents()) {
				this.addListenerToComponentChildren(c);
			}
		}
		
		this.components.add(d);
		d.addFocusListener(this);
	}

	@Override
	public void focusGained(final FocusEvent e) { }

	@Override
	public void focusLost(final FocusEvent e) {
		
		/*
		 * This has to be invoked after all pending EDT events are done,
		 * because it is important that this executed after some other
		 * component got focus maybe.
		 */
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				boolean focusTotallyLost = true;

				/*
				 * If any of the children or the parent has focus, the focus is
				 * not lost totally.
				 */
				for (Component c : components) {
					if (c.hasFocus()) {
						focusTotallyLost = false;
					}
				}

				if (focusTotallyLost) {
					parent.dispose();
				}
			}
		});
	}
}
